﻿using System.Collections.Generic;
using System.Runtime.Serialization;
using NCMIS.ObjectModel.MetaData;

namespace NCMIS.ObjectModel
{
    /// <summary>
    /// Represents a collection of CMIS properties.
    /// </summary>
    [DataContract(Namespace = CmisNs.Cmis)]
    public class CmisProperties
    {
        /// <summary>
        /// The CMIS properties.
        /// </summary>
        [DataMember(Name = "properties")]
        public CmisProperty[] Items
        {
            get;
            set;
        }

        #region Non-DataContract Members

        /// <summary>
        /// Gets the <see cref="NCMIS.ObjectModel.CmisPropertyId"/> instance of the cmis:baseTypeId property, from the Items collection.
        /// Not included in the DataContract.
        /// </summary>
        [IgnoreDataMember]
        public CmisPropertyId BaseTypeId
        {
            get { return this.GetItem(CmisPropertyDefinitionId.BaseTypeId) as CmisPropertyId; }
        }

        /// <summary>
        /// Gets the <see cref="NCMIS.ObjectModel.CmisPropertyString"/> instance of the cmis:contentStreamFileName property, from the Items collection.
        /// Not included in the DataContract.
        /// </summary>
        [IgnoreDataMember]
        public CmisPropertyString ContentStreamFileName
        {
            get { return this.GetItem(CmisPropertyDefinitionId.ContentStreamFileName) as CmisPropertyString; }
        }

        /// <summary>
        /// Gets the <see cref="NCMIS.ObjectModel.CmisPropertyString"/> instance of the cmis:contentStreamMimeType property, from the Items collection.
        /// Not included in the DataContract.
        /// </summary>
        [IgnoreDataMember]
        public CmisPropertyString ContentStreamMimeType
        {
            get { return this.GetItem(CmisPropertyDefinitionId.ContentStreamMimeType) as CmisPropertyString; }
        }

        /// <summary>
        /// Gets the <see cref="NCMIS.ObjectModel.CmisPropertyInteger"/> instance of the cmis:contentStreamLength property, from the Items collection.
        /// Not included in the DataContract.
        /// </summary>
        [IgnoreDataMember]
        public CmisPropertyInteger ContentStreamLength
        {
            get { return this.GetItem(CmisPropertyDefinitionId.ContentStreamLength) as CmisPropertyInteger; }
        }

        /// <summary>
        /// Gets the <see cref="NCMIS.ObjectModel.CmisPropertyString"/> instance of the cmis:createdBy property, from the Items collection.
        /// Not included in the DataContract.
        /// </summary>
        [IgnoreDataMember]
        public CmisPropertyString CreatedBy
        {
            get { return this.GetItem(CmisPropertyDefinitionId.CreatedBy) as CmisPropertyString; }
        }

        /// <summary>
        /// Gets the <see cref="NCMIS.ObjectModel.CmisPropertyDateTime"/> instance of the cmis:creationDate property, from the Items collection.
        /// Not included in the DataContract.
        /// </summary>
        [IgnoreDataMember]
        public CmisPropertyDateTime CreationDate
        {
            get { return this.GetItem(CmisPropertyDefinitionId.CreationDate) as CmisPropertyDateTime; }
        }        

        /// <summary>
        /// Gets the <see cref="NCMIS.ObjectModel.CmisPropertyDateTime"/> instance of the cmis:lastModificationDate property, from the Items collection.
        /// Not included in the DataContract.
        /// </summary>
        [IgnoreDataMember]
        public CmisPropertyDateTime LastModificationDate
        {
            get { return this.GetItem(CmisPropertyDefinitionId.LastModificationDate) as CmisPropertyDateTime; }
        }

        /// <summary>
        /// Gets the <see cref="NCMIS.ObjectModel.CmisPropertyString"/> instance of the cmis:lastModifiedBy property, from the Items collection.
        /// Not included in the DataContract.
        /// </summary>
        [IgnoreDataMember]
        public CmisPropertyString LastModifiedBy
        {
            get { return this.GetItem(CmisPropertyDefinitionId.LastModifiedBy) as CmisPropertyString; }
        }

        /// <summary>
        /// Gets the <see cref="NCMIS.ObjectModel.CmisPropertyString"/> instance of the cmis:name property, from the Items collection.
        /// Not included in the DataContract.
        /// </summary>
        [IgnoreDataMember]
        public CmisPropertyString Name
        {
            get { return this.GetItem(CmisPropertyDefinitionId.Name) as CmisPropertyString; }
        }

        /// <summary>
        /// Gets the <see cref="NCMIS.ObjectModel.CmisPropertyId"/> instance of the cmis:objectId property, from the Items collection.
        /// Not included in the DataContract.
        /// </summary>
        [IgnoreDataMember]
        public CmisPropertyId ObjectId
        {
            get { return this.GetItem(CmisPropertyDefinitionId.ObjectId) as CmisPropertyId; }
        }

        /// <summary>
        /// Gets the <see cref="NCMIS.ObjectModel.CmisPropertyId"/> instance of the cmis:objectTypeId property, from the Items collection.
        /// Not included in the DataContract.
        /// </summary>
        [IgnoreDataMember]
        public CmisPropertyId ObjectTypeId
        {
            get { return this.GetItem(CmisPropertyDefinitionId.ObjectTypeId) as CmisPropertyId; }
        }

        /// <summary>
        /// Gets the <see cref="NCMIS.ObjectModel.CmisPropertyId"/> instance of the cmis:parentId property, from the Items collection.
        /// Not included in the DataContract.
        /// </summary>
        [IgnoreDataMember]
        public CmisPropertyId ParentId
        {
            get { return this.GetItem(CmisPropertyDefinitionId.ParentId) as CmisPropertyId; }
        }

        /// <summary>
        /// Gets the <see cref="NCMIS.ObjectModel.CmisPropertyId"/> instance of the cmis:path property, from the Items collection.
        /// Not included in the DataContract.
        /// </summary>
        [IgnoreDataMember]
        public CmisPropertyString Path
        {
            get { return this.GetItem(CmisPropertyDefinitionId.Path) as CmisPropertyString; }
        }

        #endregion

        public void Add(CmisProperty property)
        {
            List<CmisProperty> items = new List<CmisProperty>(Items);
            items.Add(property);
            Items = items.ToArray();
        }

        /// <summary>
        /// Gets a <see cref="NCMIS.ObjectModel.CmisProperty"/> from the internal property collection.
        /// </summary>
        /// <param name="propertyDefinitionId">The property definition ID of the property to get.</param>
        /// <returns>A <see cref="NCMIS.ObjectModel.CmisProperty"/> object, or null if no matching object was found.</returns>
        private CmisProperty GetItem(string propertyDefinitionId)
        {
            // TODO: Initially set the result variable to PropertyStringDefinition.DefaultValue
            CmisProperty result = null;
            foreach (CmisProperty item in this.Items)
            {
                if (item.PropertyDefinitionId.Equals(propertyDefinitionId))
                {
                    result = item;
                    break;
                }
            }
            return result;
        }
    }
}
